package com.byt.common.view.finder.addresswheelfinder.picker;

import android.app.Activity;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.byt.base.utils.TimeUtil;
import com.byt.common.view.finder.addresswheelfinder.widget.WheelView;
import com.byt.common.view.finder.entity.DateAgeBean;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import androidx.annotation.NonNull;

/**
 * 日期时间选择器，可同时选中日期及时间，另见{@link DatePicker}和{@link TimePicker}
 */
public class DateAgePicker extends WheelPicker {

    /**
     * 年月日
     */
    private ArrayList<DateAgeBean> years = new ArrayList<>();
    private ArrayList<String> months = new ArrayList<>();
    private ArrayList<String> days = new ArrayList<>();
    private String yearLabel = "/", monthLabel = "/", dayLabel = "";
    private int selectedYearIndex = 0, selectedMonthIndex = 0, selectedDayIndex = 0;
    private OnWheelListener onWheelListener;
    private OnYearMonthDayPickListener onDateTimePickListener;
    private int startYear = 1900, startMonth = 1, startDay = 1;
    private int endYear = 2050, endMonth = 12, endDay = 31;
    private int textSize = WheelView.TEXT_SIZE;
    private boolean resetWhileWheel = false;

    public DateAgePicker(Activity activity) {
        super(activity);
        setDateRangeEnd();
    }

    /**
     * 滚动时是否重置下一级的索引
     */
    public void setResetWhileWheel(boolean resetWhileWheel) {
        this.resetWhileWheel = resetWhileWheel;
    }

    /**
     * 设置范围：开始的年月日
     */
    public void setDateRangeStart(int startYear, int startMonth, int startDay) {
        this.startYear = startYear;
        this.startMonth = startMonth;
        this.startDay = startDay;
        initYearData();
    }

    /**
     * 设置范围：结束的年月日
     */
    public void setDateRangeEnd() {
        Calendar cal = Calendar.getInstance();
        this.endYear = cal.get(Calendar.YEAR);
        this.endMonth = cal.get(Calendar.MONTH) + 1;
        this.endDay = cal.get(Calendar.DAY_OF_MONTH);
        initYearData();
    }

    /**
     * 设置年月日时分的显示单位
     */
    public void setLabel(String yearLabel, String monthLabel, String dayLabel) {
        this.yearLabel = yearLabel;
        this.monthLabel = monthLabel;
        this.dayLabel = dayLabel;
    }

    /**
     * 设置默认选中的年月日时分
     */
    public void setSelectedItem(int year, int month, int day) {
        initYearData();
        changeMonthData(year);
        changeDayData(year, month);
        selectedYearIndex = findYearItemIndex(years, year);
        selectedMonthIndex = findItemIndex(months, month);
        selectedDayIndex = findItemIndex(days, day);
    }

    public void setOnWheelListener(OnWheelListener onWheelListener) {
        this.onWheelListener = onWheelListener;
    }

    public void setOnDateTimePickListener(OnYearMonthDayPickListener listener) {
        this.onDateTimePickListener = listener;
    }

    public DateAgeBean getSelectedYearValue() {
        if (years.size() <= selectedYearIndex) {
            selectedYearIndex = years.size() - 1;
        }
        return years.get(selectedYearIndex);
    }

    public String getSelectedYear() {
        if (years.size() <= selectedYearIndex) {
            selectedYearIndex = years.size() - 1;
        }
        return years.get(selectedYearIndex).getValue();
    }

    public String getSelectedMonth() {
        if (months.size() <= selectedMonthIndex) {
            selectedMonthIndex = months.size() - 1;
        }
        return months.get(selectedMonthIndex);
    }

    public String getSelectedDay() {
        if (days.size() <= selectedDayIndex) {
            selectedDayIndex = days.size() - 1;
        }
        return days.get(selectedDayIndex);
    }

    @NonNull
    @Override
    protected View makeCenterView() {
        // 如果未设置默认项，则需要在此初始化数据
        if (years.size() == 0) {
            Log.e("DateTimePicker", "init years before make view");
            initYearData();
        }
        if (months.size() == 0) {
            Log.e("DateTimePicker", "init months before make view");
            int selectedYear = TimeUtil.trimZero(getSelectedYear());
            changeMonthData(selectedYear);
        }
        if (days.size() == 0) {
            Log.e("DateTimePicker", "init days before make view");
            int selectedYear;
            selectedYear = TimeUtil.trimZero(getSelectedYear());
            int selectedMonth = TimeUtil.trimZero(getSelectedMonth());
            changeDayData(selectedYear, selectedMonth);
        }

        LinearLayout layout = new LinearLayout(activity);
        layout.setOrientation(LinearLayout.HORIZONTAL);
        layout.setGravity(Gravity.CENTER);

        final WheelView yearView = createWheelView();
        final WheelView monthView = createWheelView();
        final WheelView dayView = createWheelView();

        yearView.setLayoutParams(new LinearLayout.LayoutParams(0, WRAP_CONTENT, 1.0f));
        List<String> yearsStr = new ArrayList<>();
        for (DateAgeBean ageBean : years) {
            yearsStr.add(ageBean.getName());
        }
        yearView.setItems(yearsStr, selectedYearIndex);
        yearView.setOnItemSelectListener(new WheelView.OnItemSelectListener() {
            @Override
            public void onSelected(int index) {
                selectedYearIndex = index;
                String selectedYearStr = years.get(selectedYearIndex).getValue();
                if (onWheelListener != null) {
                    onWheelListener.onYearWheeled(selectedYearIndex, getSelectedYearValue());
                }
                Log.e("DateTimePicker", "change months after year wheeled");
                //需要根据年份及月份动态计算天数
                int selectedYear = TimeUtil.trimZero(selectedYearStr);
                changeMonthData(selectedYear);
                //月份回推
                monthView.setItems(months, selectedMonthIndex);
                if (onWheelListener != null) {
                    onWheelListener.onMonthWheeled(selectedMonthIndex, months.get(selectedMonthIndex));
                }
                //天数回推
                changeDayData(selectedYear, TimeUtil.trimZero(months.get(selectedMonthIndex)));
                dayView.setItems(days, selectedDayIndex);
                if (onWheelListener != null) {
                    onWheelListener.onDayWheeled(selectedDayIndex, days.get(selectedDayIndex));
                }
            }
        });
        layout.addView(yearView);
        if (!TextUtils.isEmpty(yearLabel)) {
            TextView labelView = createLabelView();
            labelView.setTextSize(textSize);
            labelView.setText(yearLabel);
            layout.addView(labelView);
        }

        monthView.setLayoutParams(new LinearLayout.LayoutParams(0, WRAP_CONTENT, 1.0f));
        monthView.setItems(months, selectedMonthIndex);
        monthView.setOnItemSelectListener(new WheelView.OnItemSelectListener() {
            @Override
            public void onSelected(int index) {
                selectedMonthIndex = index;
                String selectedMonthStr = months.get(selectedMonthIndex);
                if (onWheelListener != null) {
                    onWheelListener.onMonthWheeled(selectedMonthIndex, selectedMonthStr);
                }
                Log.e("DateTimePicker", "change days after month wheeled");
                String selectDay = days.get(selectedDayIndex);
                int selectedYear = TimeUtil.trimZero(getSelectedYear());
                changeDayData(selectedYear, TimeUtil.trimZero(selectedMonthStr));
                if (resetWhileWheel) {
                    if (days.contains(selectDay)) {
                        selectedDayIndex = days.indexOf(selectDay);
                    } else {
                        if (days.size() > 0 && selectedDayIndex >= days.size()) {
                            selectedDayIndex = days.size() - 1;
                        } else {
                            selectedDayIndex = 0;
                        }
                    }
                }
                dayView.setItems(days, selectedDayIndex);
                if (onWheelListener != null) {
                    onWheelListener.onDayWheeled(selectedDayIndex, days.get(selectedDayIndex));
                }
            }
        });
        layout.addView(monthView);
        if (!TextUtils.isEmpty(monthLabel)) {
            TextView labelView = createLabelView();
            labelView.setTextSize(textSize);
            labelView.setText(monthLabel);
            layout.addView(labelView);
        }
        dayView.setLayoutParams(new LinearLayout.LayoutParams(0, WRAP_CONTENT, 1.0f));
        dayView.setItems(days, selectedDayIndex);
        dayView.setOnItemSelectListener(new WheelView.OnItemSelectListener() {
            @Override
            public void onSelected(int index) {
                selectedDayIndex = index;
                if (onWheelListener != null) {
                    onWheelListener.onDayWheeled(selectedDayIndex, days.get(selectedDayIndex));
                }
            }
        });
        layout.addView(dayView);
        if (!TextUtils.isEmpty(dayLabel)) {
            TextView labelView = createLabelView();
            labelView.setTextSize(textSize);
            labelView.setText(dayLabel);
            layout.addView(labelView);
        }
        return layout;
    }

    @Override
    protected void onSubmit() {
        if (onDateTimePickListener == null) {
            return;
        }
        DateAgeBean year = getSelectedYearValue();
        String month = getSelectedMonth();
        String day = getSelectedDay();
        (onDateTimePickListener).onDateTimePicked(year, month, day);
    }

    private int findYearItemIndex(ArrayList<DateAgeBean> items, int item) {
        //折半查找有序元素的索引
        int index = Collections.binarySearch(items, item, new Comparator<Object>() {
            @Override
            public int compare(Object lhs, Object rhs) {
                DateAgeBean ageBean = (DateAgeBean) lhs;
                String lhsStr = ageBean.getValue();
                String rhsStr = rhs.toString();
                lhsStr = lhsStr.startsWith("0") ? lhsStr.substring(1) : lhsStr;
                rhsStr = rhsStr.startsWith("0") ? rhsStr.substring(1) : rhsStr;
                try {
                    return Integer.parseInt(lhsStr) - Integer.parseInt(rhsStr);
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                    return 0;
                }
            }
        });
        if (index < 0) {
            throw new IllegalArgumentException("Item[" + item + "] out of range");
        }
        return index;
    }

    private int findItemIndex(ArrayList<String> items, int item) {
        //折半查找有序元素的索引
        int index = Collections.binarySearch(items, item, new Comparator<Object>() {
            @Override
            public int compare(Object lhs, Object rhs) {
                String lhsStr = lhs.toString();
                String rhsStr = rhs.toString();
                lhsStr = lhsStr.startsWith("0") ? lhsStr.substring(1) : lhsStr;
                rhsStr = rhsStr.startsWith("0") ? rhsStr.substring(1) : rhsStr;
                try {
                    return Integer.parseInt(lhsStr) - Integer.parseInt(rhsStr);
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                    return 0;
                }
            }
        });
        if (index < 0) {
            throw new IllegalArgumentException("Item[" + item + "] out of range");
        }
        return index;
    }

    private void initYearData() {
        years.clear();
        if (startYear == endYear) {
            years.add(new DateAgeBean(startYear + "年(" + (Calendar.getInstance().get(Calendar.YEAR) - startYear) + "岁)", String.valueOf(startYear),(Calendar.getInstance().get(Calendar.YEAR) - startYear)));
        } else if (startYear < endYear) {
            //年份正序
            for (int i = startYear; i <= endYear; i++) {
                years.add(new DateAgeBean(i + "年(" + (Calendar.getInstance().get(Calendar.YEAR) - i) + "岁)", String.valueOf(i),(Calendar.getInstance().get(Calendar.YEAR) - i)));
            }
        } else {
            //年份逆序
            for (int i = startYear; i >= endYear; i--) {
                years.add(new DateAgeBean(i + "年(" + (Calendar.getInstance().get(Calendar.YEAR) - i) + "岁)", String.valueOf(i),(Calendar.getInstance().get(Calendar.YEAR) - i)));
            }
        }
        if (!resetWhileWheel) {
            int index = years.indexOf(TimeUtil.fillZero(Calendar.getInstance().get(Calendar.YEAR)));
            if (index == -1) {
                //当前设置的年份不在指定范围，则默认选中范围开始的年
                selectedYearIndex = 0;
            } else {
                selectedYearIndex = index;
            }
        }
    }

    private void changeMonthData(int selectedYear) {
        String preSelectMonth = "";
        if (!resetWhileWheel) {
            if (months.size() > selectedMonthIndex) {
                preSelectMonth = months.get(selectedMonthIndex);
            } else {
                preSelectMonth = TimeUtil.fillZero(Calendar.getInstance().get(Calendar.MONTH) + 1);
            }
            Log.e("DateTimePicker", "preSelectMonth=" + preSelectMonth);
        }
        months.clear();
        if (startMonth < 1 || endMonth < 1 || startMonth > 12 || endMonth > 12) {
            throw new IllegalArgumentException("Month out of range [1-12]");
        }
        if (startYear == endYear) {
            if (startMonth > endMonth) {
                for (int i = endMonth; i >= startMonth; i--) {
                    months.add(TimeUtil.fillZero(i));
                }
            } else {
                for (int i = startMonth; i <= endMonth; i++) {
                    months.add(TimeUtil.fillZero(i));
                }
            }
        } else if (selectedYear == startYear) {
            for (int i = startMonth; i <= 12; i++) {
                months.add(TimeUtil.fillZero(i));
            }
        } else if (selectedYear == endYear) {
            for (int i = 1; i <= endMonth; i++) {
                months.add(TimeUtil.fillZero(i));
            }
        } else {
            for (int i = 1; i <= 12; i++) {
                months.add(TimeUtil.fillZero(i));
            }
        }
        if (!resetWhileWheel) {
            //当前设置的月份不在指定范围，则默认选中范围开始的月份
            int preSelectMonthIndex = months.indexOf(preSelectMonth);
            selectedMonthIndex = preSelectMonthIndex == -1 ? 0 : preSelectMonthIndex;
        }
    }

    private void changeDayData(int selectedYear, int selectedMonth) {
        int maxDays = TimeUtil.calculateDaysInMonth(selectedYear, selectedMonth);
        String preSelectDay = "";
        if (!resetWhileWheel) {
            if (selectedDayIndex >= maxDays) {
                //如果之前选择的日是之前年月的最大日，则日自动为该年月的最大日
                selectedDayIndex = maxDays - 1;
            }
            if (days.size() > selectedDayIndex) {
                //年或月变动时，保持之前选择的日不动
                preSelectDay = days.get(selectedDayIndex);
            } else {
                preSelectDay = TimeUtil.fillZero(Calendar.getInstance().get(Calendar.DAY_OF_MONTH));
            }
            Log.e("DateTimePicker", "maxDays=" + maxDays + ", preSelectDay=" + preSelectDay);
        }
        days.clear();
        if (selectedYear == startYear && selectedMonth == startMonth
                && selectedYear == endYear && selectedMonth == endMonth) {
            //开始年月及结束年月相同情况
            for (int i = startDay; i <= endDay; i++) {
                days.add(TimeUtil.fillZero(i));
            }
        } else if (selectedYear == startYear && selectedMonth == startMonth) {
            //开始年月相同情况
            for (int i = startDay; i <= maxDays; i++) {
                days.add(TimeUtil.fillZero(i));
            }
        } else if (selectedYear == endYear && selectedMonth == endMonth) {
            //结束年月相同情况
            for (int i = 1; i <= endDay; i++) {
                days.add(TimeUtil.fillZero(i));
            }
        } else {
            for (int i = 1; i <= maxDays; i++) {
                days.add(TimeUtil.fillZero(i));
            }
        }
        if (!resetWhileWheel) {
            //当前设置的日子不在指定范围，则默认选中范围开始的日子
            int preSelectDayIndex = days.indexOf(preSelectDay);
            selectedDayIndex = preSelectDayIndex == -1 ? 0 : preSelectDayIndex;
        }
    }

    public interface OnWheelListener {

        void onYearWheeled(int index, DateAgeBean year);

        void onMonthWheeled(int index, String month);

        void onDayWheeled(int index, String day);

    }

    public interface OnYearMonthDayPickListener {

        void onDateTimePicked(DateAgeBean year, String month, String day);
    }
}